home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / scheme / pcscheme / geneva / sources.exe / SOURCES / LISP / SEQUENCE.LSP < prev   
Encoding:
Lisp/Scheme  |  1990-09-09  |  13.9 KB  |  451 lines

  1. ;; PC Scheme Common Lisp Compatibility Package
  2. ;;
  3. ;; (c) Copyright 1990 Carl W. Hoffman.  All rights reserved.
  4. ;;
  5. ;; This file may be freely copied, distributed, or modified for non-commercial
  6. ;; use provided that this copyright notice is not removed.  For further
  7. ;; information about other utilities for Common Lisp or Scheme, contact the
  8. ;; following address:
  9. ;;
  10. ;;   Carl W. Hoffman, 363 Marlborough Street, Boston, MA 02115, U.S.A.
  11. ;;   Internet: CWH@AI.MIT.EDU    CompuServe: 76416,3365    Fax: 617-262-4284
  12.  
  13. ;; Sequences and Lists
  14.  
  15. ;; Note that we can't use the name SEQUENCE (or the name of any other Scheme
  16. ;; special form) as the name of a parameter.  Actually, SEQUENCE isn't defined
  17. ;; in R^3RS, but it is used in Abelson & Sussman, so PC Scheme defines it
  18. ;; anyway.
  19.  
  20. ;; Taken from CLtL first edition p. 265
  21.  
  22. (defun list-length (x)
  23.   (do ((n 0 (+ n 2))                ; Counter
  24.        (fast x (cddr fast))         ; Fast pointer: leaps by 2.
  25.        (slow x (cdr slow)))         ; Slow pointer: leaps by 1.
  26.       (nil)
  27.     ;; If fast pointer hist the end, return the count.
  28.     (when (endp fast) (return n))
  29.     (when (endp (cdr fast)) (return (+ n 1)))
  30.     ;; If fast pointer eventually equals slow pointer,
  31.     ;;  then we must be stuck in a circular list.
  32.     ;; (A deeper property is the converse:  if we are
  33.     ;;  stuck in a circular list, then eventually the
  34.     ;;  fast pointer will equal the slow pointer.
  35.     ;;  That fact justifies this implementation.)
  36.     (when (and (eq fast slow) (> n 0)) (return nil))))
  37.  
  38. (defun nth (n list)
  39.   (when (or (not (integerp n)) (< n 0))
  40.     (error "The first argument to NTH, ~S, is not a non-negative integer."
  41.            n))
  42.   (list-ref list n))
  43.  
  44. (defun nthcdr (n list)
  45.   (when (or (not (integerp n)) (< n 0))
  46.     (error "The first argument to NTHCDR, ~S, is not a non-negative integer."
  47.            n))
  48.   (list-tail list n))
  49.  
  50. ;; APPEND! is the PC Scheme name for NCONC.
  51.  
  52. (defun nconc (&rest lists)
  53.   (do ((l lists (cdr l)))
  54.       ((null l))
  55.     (let ((list (car l)))
  56.       (cond ((null list))
  57.             ((not (consp list))
  58.              (error "One of the arguments to NCONC, ~S, is not a list."
  59.                     list))
  60.             (else
  61.               (do ((x list (cdr x)))
  62.                   (nil)
  63.                 (when (null (cdr x))
  64.                   (setf (cdr x) (cadr l))
  65.                   (return)))))))
  66.    (car lists))
  67.  
  68. ;; This could be written more efficiently.
  69.  
  70. (defun nreconc (x y)
  71.   (nconc (nreverse x) y))
  72.  
  73. ;; p. 250
  74. ;; Just lists for now.
  75.  
  76. (defun some (predicate seq)
  77.   (dolist (x seq)
  78.     (let ((y (funcall predicate x)))
  79.       (when y
  80.         (return-from some y))))
  81.   nil)
  82.  
  83. (defun every (predicate seq)
  84.   (dolist (x seq)
  85.     (unless (funcall predicate x)
  86.       (return-from every nil)))
  87.   t)
  88.  
  89. (defun notany (predicate seq)
  90.   (dolist (x seq)
  91.     (when (funcall predicate x)
  92.       (return-from every nil)))
  93.   t)
  94.  
  95. (defun notevery (predicate seq)
  96.   (dolist (x seq)
  97.     (unless (funcall predicate x)
  98.       (return-from notevery t)))
  99.   nil)
  100.  
  101. (defun-clcp %%check-index-arg (fcn name value)
  102.   (unless (or (null value)
  103.               (and (integerp value) (>= value 0)))
  104.     (error "The :~A argument to ~A, ~S, is not a non-negative integer or NIL."
  105.            name fcn value)))
  106.  
  107. (defmacro check-index-arg (fcn var)
  108.   `(%%check-index-arg ',fcn ',var ,var))
  109.  
  110. (defun-clcp %%compare-index-args
  111.             (fcn start-name end-name start-value end-value)
  112.   (when (> start-value end-value)
  113.     (error "The :~A argument to ~A, ~S, is greater than the :~A argument, ~S."
  114.            start-name fcn start-value end-name end-value)))
  115.  
  116. (defmacro compare-index-args (fcn start-var end-var)
  117.   `(%%compare-index-args ',fcn ',start-var ',end-var ,start-var ,end-var))
  118.  
  119. (defun-clcp %%fill (seq item start end)
  120.   (check-index-arg fill start)
  121.   (check-index-arg fill end)
  122.   (unless start
  123.     (setq start 0))
  124.   (unless end
  125.     (setq end (length seq)))
  126.   (compare-index-args fill start end)
  127.   (cond ((listp seq)
  128.          (let ((cdr-seq seq))
  129.            (dotimes (i start)
  130.              (pop cdr-seq))
  131.            (dotimes (i (- end start))
  132.              (when (null cdr-seq) (return))
  133.              (setf (car cdr-seq) item)
  134.              (pop cdr-seq))))
  135.         ((stringp seq)
  136.          (substring-fill! seq start end item))
  137.         ((vectorp seq)
  138.          (do ((i start (1+ i)))
  139.              ((= i end))
  140.            (setf (svref seq i) item)))
  141.         (else
  142.           (error "The first argument to FILL, ~S, is not a sequence."
  143.                  seq)))
  144.   seq)
  145.  
  146. (defun-clcp %%replace-string (string1 string2 start1 start2 count)
  147.   (dotimes (i count)
  148.     (setf (char string1 (+ start1 i))
  149.           (char string2 (+ start2 i)))))
  150.  
  151. (defun-clcp %%replace-vector (vector1 vector2 start1 start2 count)
  152.   (dotimes (i count)
  153.     (setf (svref vector1 (+ start1 i))
  154.           (svref vector2 (+ start2 i)))))
  155.  
  156. (defun-clcp %%replace (seq1 seq2 start1 end1 start2 end2)
  157.   (check-index-arg replace start1)
  158.   (check-index-arg replace end1)
  159.   (check-index-arg replace start2)
  160.   (check-index-arg replace end2)
  161.   (unless start1
  162.     (setq start1 0))
  163.   (unless start2
  164.     (setq start2 0))
  165.   (unless end1
  166.     (setq end1 (length seq1)))
  167.   (unless end2
  168.     (setq end2 (length seq2)))
  169.   (compare-index-args replace start1 end1)
  170.   (compare-index-args replace start2 end2)
  171.   (let ((count (min (- end1 start1) (- end2 start2))))
  172.     (cond ((listp seq1)
  173.            (unless (listp seq2)
  174.              (error "The second argument to REPLACE, ~S, is not a list."
  175.                     seq2))
  176.            (let ((cdr-seq1 seq1)
  177.                  (cdr-seq2 seq2))
  178.              (dotimes (i start1) (pop cdr-sq1))
  179.              (dotimes (i start2) (pop cdr-sq2))
  180.              (dotimes (i count)
  181.                (setf (car cdr-sq1) (car cdr-sq2))
  182.                (pop cdr-sq1)
  183.                (pop cdr-sq2))))
  184.           ((stringp seq1)
  185.            (unless (stringp seq2)
  186.              (error "The second argument to REPLACE, ~S, is not a string."
  187.                     seq2))
  188.            (%%replace-string seq1 seq2 start1 start2 count))
  189.           ((vectorp seq1)
  190.            (unless (vectorp seq2)
  191.              (error "The second argument to REPLACE, ~S, is not a vector."
  192.                     seq2))
  193.            (%%replace-vector seq1 seq2 start1 start2 count))
  194.           (else
  195.             (error "The first argument to REPLACE, ~S, is not a sequence."
  196.                    seq1))))
  197.   seq1)
  198.  
  199. ;; This is defined for sequences but is currently only implemented for lists.
  200.  
  201. (defun-clcp %%delete (thing seq test count)
  202.   (unless (or (null count)
  203.               (and (integerp count) (>= count 0)))
  204.     (error "The :COUNT argument to DELETE, ~S, ~
  205.             is not a non-negative integer or NIL."
  206.            count))
  207.   (if (and (integerp count) (<= count 0))
  208.       seq
  209.       (let ((i count)
  210.             (previous nil)
  211.             (result seq))
  212.         (do ((l seq (cdr l)))
  213.             ((or (null l)
  214.                  (and i (zerop i))))
  215.           (let ((x (car l)))
  216.             (if (not (or (and test (test thing x))
  217.                          (eql thing x)))
  218.                 (setq previous l)
  219.                 (progn
  220.                   (when i (decf i))
  221.                   (if (eq result l)
  222.                       (pop result)
  223.                       (progn
  224.                         (if (null previous)
  225.                             (setq previous result))
  226.                         (setf (cdr previous) (cdr l))))))))
  227.         result)))
  228.  
  229. ;; This is defined for sequences but is currently only implemented for lists.
  230.  
  231. (defun-clcp %%find (item seq test key)
  232.   (do ((l seq (cdr l)))
  233.       ((null l) nil)
  234.     (let* ((x (car l))
  235.            (kx (if key (key x) x)))
  236.       (when (or (and test (test item kx))
  237.                 (eql item kx))
  238.         (return x)))))
  239.  
  240. (defun-clcp %%member (item list test key)
  241.   (do ((l list (cdr l)))
  242.       ((null l) nil)
  243.     (let ((x (car l)))
  244.       (if key (key x))
  245.       (when (or (and test (test item x))
  246.                 (eql item x))
  247.         (return l)))))
  248.  
  249. (defun-clcp %%assoc (item alist test)
  250.   (do ((l alist (cdr l)))
  251.       ((null l) nil)
  252.     (let* ((pair (car l))
  253.            (key (car pair)))
  254.       (when (or (and test (test item key))
  255.                 (eql item key))
  256.         (return pair)))))
  257.  
  258. ;; Extend this to indicate when a keyword is not present in ARG-LIST.
  259.  
  260. (defun-clcp parse-keywords (key-list arg-list)
  261.   (let ((result nil))
  262.     ;; Scan the list of defined keywords.
  263.     (do ((k key-list (cdr k)))
  264.         ((null k))
  265.       (let ((seen? nil))
  266.         (do ((a arg-list (cddr a)))
  267.             ((null a))
  268.           (when (null (cdr a))
  269.             (error "The keyword ~A appears at the end of the argument list."
  270.                    (car a)))
  271.           (when (eq (car k) (car a))
  272.             (when seen?
  273.               (error "The keyword ~A appears twice in the argument list."
  274.                      (car a)))
  275.             (push (cadr a) result)
  276.             (setq seen? t)))
  277.         (unless seen?
  278.           (push nil result))))
  279.     ;; Scan the arguments looking for undefined keywords.
  280.     (do ((a arg-list (cddr a)))
  281.         ((null a))
  282.       (unless (member (car a) key-list)
  283.         (error "The keyword ~A is undefined." (car a))))
  284.     (nreverse result)))
  285.  
  286. ;; These only allow the use of keywords at compile time.  Later, when we have
  287. ;; a real translator, these should be reimplemented as functions which
  288. ;; recognize keyword arguments at runtime.
  289.  
  290. ;; p. 252
  291.  
  292. (defmacro fill (seq item &rest keywords)
  293.   `(%%fill
  294.      ,seq ,item . ,(parse-keywords '(:start :end) keywords)))
  295.  
  296. (defmacro replace (seq1 seq2 &rest keywords)
  297.   `(%%replace
  298.      ,seq1 ,seq2 . ,(parse-keywords '(:start1 :end1 :start2 :end2) keywords)))
  299.  
  300. ;; p. 254
  301.  
  302. (defmacro delete (item list &rest keywords)
  303.   (let ((parsed (parse-keywords '(:test :count) keywords)))
  304.     (if (every (function null) parsed)
  305.         `(delq! ,item ,list)
  306.         `(%%delete ,item ,list . ,parsed))))
  307.  
  308. ;; p. 257
  309.  
  310. (defmacro find (item seq &rest keywords)
  311.   `(%%find ,item ,seq . ,(parse-keywords '(:test :key) keywords)))
  312.  
  313. ;; p. 273
  314.  
  315. (defun subst (new old tree)
  316.   (cond ((eq old tree)
  317.          new)
  318.         ((not (consp tree))
  319.          tree)
  320.         (else
  321.           (cons (subst new old (car tree)) (subst new old (cdr tree))))))
  322.  
  323. ;; p. 274
  324.  
  325. (defun nsubst (new old tree)
  326.   (cond ((eq old tree)
  327.          new)
  328.         ((not (consp tree))
  329.          tree)
  330.         (else
  331.           (setf (car tree) (nsubst new old (car tree)))
  332.           (setf (cdr tree) (nsubst new old (cdr tree)))
  333.           tree)))
  334.  
  335. ;; p. 275
  336.  
  337. (defmacro member (item list &rest keywords)
  338.   (let ((parsed (parse-keywords '(:test :key) keywords)))
  339.     (if (every (function null) parsed)
  340.         `(scheme-member ,item ,list)
  341.         `(%%member ,item ,list . ,parsed))))
  342.  
  343. ;; p. 276
  344.  
  345. (defun adjoin (item list)
  346.   (if (member item list) list (cons item list)))
  347.  
  348. ;; p. 280
  349.  
  350. (defmacro assoc (item alist &rest keywords)
  351.   (let ((parsed (parse-keywords '(:test) keywords)))
  352.     (if (null (first parsed))
  353.         `(scheme-assoc ,item ,alist)
  354.         `(%%assoc ,item ,alist . ,parsed))))
  355.  
  356. ;; p. 248
  357.  
  358. (defun elt (seq index)
  359.   (cond ((stringp seq)
  360.          (string-ref seq index))
  361.         ((vectorp seq)
  362.          (vector-ref seq index))
  363.         ((listp seq)
  364.          (nth index seq))
  365.         (else
  366.          (error "The first argument to ELT, ~S, is not a sequence." seq))))
  367.  
  368. (defun subseq (seq start &optional end)
  369.   (cond ((listp seq)
  370.          (dotimes (i start) (pop seq))
  371.          (if (null end)
  372.              (mapcar (lambda (x) x) seq)
  373.              (let ((result '()))
  374.                (dotimes (i (- end start))
  375.                  (push (pop seq) result))
  376.                (nreverse result))))
  377.         ((vectorp seq)
  378.          (let* ((length (- (or end (vector-length seq)) start))
  379.                 (new-vector (make-vector length)))
  380.            (dotimes (i length)
  381.              (setf (svref new-vector i) (svref seq (+ i start))))
  382.            new-vector))
  383.         ((stringp seq)
  384.          (substring seq start (or end (string-length seq))))
  385.         (else
  386.           (error "The first argument to SUBSEQ, ~S, is not a sequence."
  387.                  seq))))
  388.  
  389. (defun copy-seq (seq)
  390.   (cond ((listp seq)
  391.          (mapcar (lambda (x) x) seq))
  392.         ((stringp seq)
  393.          (let* ((length (string-length seq))
  394.                 (new-string (make-string length)))
  395.            (dotimes (i length)
  396.              (setf (char new-string i) (char seq i)))
  397.            new-string))
  398.         ((vectorp seq)
  399.          (let* ((length (vector-length seq))
  400.                 (new-vector (make-vector length)))
  401.            (dotimes (i length)
  402.              (setf (svref new-vector i) (svref seq i)))
  403.            new-vector))
  404.         (else
  405.           (error "The first argument to COPY-SEQ, ~S, is not a sequence."
  406.                  seq))))
  407.  
  408. (defun length (seq)
  409.   (cond ((listp seq)
  410.          (scheme-length seq))
  411.         ((stringp seq)
  412.          (string-length seq))
  413.         ((vectorp seq)
  414.          (vector-length seq))
  415.         (else
  416.           (error "The first argument to LENGTH, ~S, is not a sequence."
  417.                  seq))))
  418.  
  419. (defun concatenate (type &rest sequences)
  420.   (case type
  421.     (string
  422.       (apply string-append sequences))
  423.     (list
  424.       (apply append sequences))
  425.     (else
  426.       (error "The first argument to CONCATENATE, ~S, ~
  427.               is not a known sequence type specifier."
  428.              type))))
  429.  
  430. ;; p. 268
  431.  
  432. (defun copy-list (list)
  433.   (if (null list)
  434.       ()
  435.       (let* ((result (cons (car list) ()))
  436.              (next result))
  437.         (do ((l (cdr list) (cdr l)))
  438.             ((null l))
  439.           (setf (cdr next) (cons (car l) ()))
  440.           (pop next))
  441.         result)))
  442.  
  443. ;; p. 302
  444.  
  445. (defmacro make-string (size &rest keywords)
  446.   (let ((initial-element
  447.           (first (parse-keywords '(:initial-element) keywords))))
  448.     (if (null initial-element)
  449.         `(scheme-make-string ,size)
  450.         `(scheme-make-string ,size ,initial-element))))
  451.